
package com.fly.common.aop;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import com.fly.common.utils.HttpContextUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 系统日志，切面处理类
 * 
 * @author 00fly
 * @version [版本号, 2019年12月6日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Slf4j
@Aspect
@Component
public class SysLogAspect
{
    @Pointcut("@annotation(com.fly.common.aop.SysLog)")
    public void logPointCut()
    {
    }
    
    @Before("logPointCut()")
    public void beforMethod(JoinPoint point)
    {
        log.info("@Before");
    }
    
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point)
        throws Throwable
    {
        log.info("@Around");
        StopWatch clock = new StopWatch();
        clock.start();
        // 执行方法
        Object result = point.proceed();
        clock.stop();
        log.info("@Around end");
        printInfo(point, clock.getTotalTimeMillis());
        return result;
    }
    
    @After("logPointCut()")
    public void afterMethod(JoinPoint point)
    {
        log.info("@After");
    }
    
    @AfterReturning("logPointCut()")
    public void afterReturningMethod(JoinPoint point)
    {
        log.info("@AfterReturning");
    }
    
    @AfterThrowing(value = "logPointCut()", throwing = "ex")
    public void afterThrowing(JoinPoint point, Exception ex)
    {
        log.info("@AfterThrowing");
        String methodName = point.getSignature().getName();
        List<Object> args = Arrays.asList(point.getArgs());
        log.info("连接点方法为：{}, 参数为：{}, 异常为：", methodName, args, ex);
    }
    
    protected void printInfo(ProceedingJoinPoint joinPoint, long time)
    {
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        Method method = signature.getMethod();
        SysLog syslog = method.getAnnotation(SysLog.class);
        
        // 请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        // 请求的参数
        Object[] args = joinPoint.getArgs();
        
        // 获取request
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        
        log.info("--------系统日志，切面处理类-----------");
        log.info("{}", syslog.value());
        log.info("className {}", className);
        log.info("methodName{}", methodName);
        log.info("request ：{}", request);
        log.info("args：      {}", args);
        log.info("ms：         {}", time);
    }
}
